//package com.chuck.learning.NIO;
//
//import java.io.IOException;
//import java.util.ArrayList;
//import java.util.Set;
//import org.apache.commons.lang.StringUtils;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.util.CollectionUtils;
//
//import com.dianping.cat.Cat;
//import com.starcharge.iot.model.ParamInfo;
//import com.starcharge.iot.service.LogService;
//import com.starcharge.iot.utils.Constants;
//import com.starcharge.iot.utils.ProtocolUtils;
//import com.starcharge.iot.utils.RedisUtils;
//import io.netty.channel.ChannelDuplexHandler;
//import io.netty.channel.ChannelHandlerContext;
//import io.netty.channel.ChannelPromise;
//import io.netty.channel.ChannelHandler.Sharable;
//import io.netty.handler.timeout.IdleState;
//import io.netty.handler.timeout.IdleStateEvent;
//
///**
// * 心跳包
// *
// * @author Administrator
// *
// */
//@Sharable
//public class HeartbeatHandler extends ChannelDuplexHandler {
//
//    private static final Logger logger = LoggerFactory.getLogger(HeartbeatHandler.class);
//
//    /**
//     * 创建链接
//     *
//     * @param ctx 通道上下文
//     * @throws Exception
//     */
//    public void channelActive(ChannelHandlerContext ctx) {
//
//        try {
//            super.channelActive(ctx);
//        } catch (Exception e) {
//            // TODO Auto-generated catch block
//    		LogService.error(null, "channelActive", null, "error:" + e.getMessage(), e);
//        }
//
//        // 初始化自定义channel属性
//        SChannelContext.addChannel(ctx);
//    }
//
//    /**
//     * 关闭链接
//     * @param ctx 通道上下文
//     * @throws Exception
//     */
//    public void channelInactive(ChannelHandlerContext ctx) {
//    	Set<String> stubIds = SChannelContext.getStubIdFromChannel(ctx);
//    	if(!CollectionUtils.isEmpty(stubIds) && Constants.stubStatuss.getAllPresent(stubIds) != null) {
//    		Constants.stubStatuss.invalidateAll(stubIds);
//    	}
//        // 清理channel相应属性
//        SChannelContext.pushToOffline(ctx);
//        Cat.getProducer().logEvent("Iot2.0OnOrOffLine", "pyOffLine");
//        try {
//            super.channelInactive(ctx);
//        } catch (Exception e) {
//            // TODO Auto-generated catch block
//    		LogService.error(null, "channelInactive", null, "error:" + e.getMessage(), e);
//        }
//    }
//
//    /**
//     * 心跳
//     * @param ctx   通道上下文
//     * @param evt   事件
//     * @throws Exception
//     */
//    @Override
//    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
//    	Set<String> stubIds = SChannelContext.getStubIdFromChannel(ctx);
//    	boolean flag = false;
//        if (evt instanceof IdleStateEvent) {
//            IdleStateEvent event = (IdleStateEvent) evt;
//            if (event.state().equals(IdleState.READER_IDLE)) {
//				String stubId = (stubIds != null && stubIds.size() > 0)
//						? StringUtils.substring(new ArrayList(stubIds).get(0).toString(), 0, 8) : null;
//				LogService.error(stubId, "heartbeat", null, "charge pile more then 5 min does not upload data, disconnect", null);
//				flag = true;
//                SChannelContext.pushToOffline(ctx);
//                ctx.close();
//
//            } else if (event.state().equals(IdleState.WRITER_IDLE)) {
//                // 通道不激活则不发送了
//                if (SChannelContext.isChannelAlive(ctx)) {
//                    if (stubIds != null && stubIds.size() > 0) {
//                        ParamInfo param = new ParamInfo();
//                        param.setServiceName("01");
//                        for (String stubId : stubIds) {
//                            // 从内存中获取充电中的桩
//                            String stubStatus = RedisUtils.get("platform:stubId:" + stubId + ":status", String.class);
//                            if (StringUtils.isNotBlank(stubStatus) && stubStatus.equals("01")) {
//                                param.setStubId(stubId);
//                                try {
//                                	// 如果充电桩在1分钟内没有回复充电桩任何内容，则主动回复
//                    				LogService.error(stubId, "heartbeat", null, "The platform is more than 1 min without sending data to charge pile, reply in charge", null);
//                                    if (param != null && param.isFrameWriteResponse()) {
//                                        ctx.channel().writeAndFlush(ProtocolUtils.encode(param));
//                                    }
//                                    break;
//                                } catch (Exception e) {
//                    				LogService.error(stubId, "heartbeat", null, "在下发心跳时候出现异常:"+ e.getMessage(), null);
//                                }
//                            }
//                        }
//                    }
//                }else{
//                	flag = true;
//                    SChannelContext.pushToOffline(ctx);
//                    ctx.close();
//                }
//            } else if (event.state().equals(IdleState.ALL_IDLE)) {
//				String stubId = (stubIds != null && stubIds.size() > 0)
//						? StringUtils.substring(new ArrayList(stubIds).get(0).toString(), 0, 8) : null;
//				LogService.error(stubId, "heartbeat", null, "charge pile more then 5 min without response, disconnect", null);
//				flag = true;
//                SChannelContext.pushToOffline(ctx);
//                ctx.close();
//            }
//        }
//        try {
//        	if(flag) {
//        		if(!CollectionUtils.isEmpty(stubIds) && Constants.stubStatuss.getAllPresent(stubIds) != null) {
//        			Constants.stubStatuss.invalidateAll(stubIds);
//        		}
//        	}
//            super.userEventTriggered(ctx, evt);
//        } catch (Exception e) {
//			LogService.error(null, "heartbeat", null, "心跳事件监听异常:"+ e.getMessage(), e);
//        }
//    }
//
//    @Override
//    public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {
//
//        try {
//            if (!(e instanceof IOException)) {
//    			LogService.error(null, "heartbeat", null, "出现未知异常:"+ e.getMessage(), e);
//            }
//        } finally {
//            ctx.close();
//        }
//    }
//
//    @Override
//    public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception {
//        super.close(ctx, future);
//    }
//
//}
